package client;

import com.esotericsoftware.minlog.Log;
import java.awt.AWTException;
import java.awt.GraphicsDevice;
import java.awt.GraphicsEnvironment;
import java.awt.MouseInfo;
import java.awt.Robot;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.util.Arrays;
import util.Monitor;
import util.Screenshot;

public class RemoteDesktopManager {

    private ClientManager client;
    private Robot robot;
    private boolean capturing;
    private GraphicsEnvironment g;
    private static ThreadLocal<byte[]> previous;

    public RemoteDesktopManager(ClientManager clientManager) {
        this.client = clientManager;

        try {
            robot = new Robot();
        } catch (AWTException ex) {
            client.writeToServerLog(Log.LEVEL_ERROR, "[RemoteDesktopManager] Failed to initialize the object", ex);
        }

        g = GraphicsEnvironment.getLocalGraphicsEnvironment();
        previous = new ThreadLocal<>();
    }

    public boolean isCapturing() {
        return capturing;
    }

    public void stopCapturing() {
        capturing = false;
    }

    public void startCapturing(final int timeBetweenFrames, final int monitor, final double quality, final double scale) {
        capturing = true;

        Thread t = new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    while (true) {
                        if (capturing) {
                            GraphicsDevice device = MouseInfo.getPointerInfo().getDevice();

                            if (monitor == Monitor.MONITOR_ACTIVE) {
                                device = MouseInfo.getPointerInfo().getDevice();
                            } else if (monitor == Monitor.MONITOR_DEFAULT) {
                                device = g.getDefaultScreenDevice();
                            }

                            BufferedImage image = robot.createScreenCapture(device.getDefaultConfiguration().getBounds());
                            byte[] frame = Screenshot.convertToByte(image, quality, scale);

                            // Only send if image has changed (too damn good for bandwidth usage!)
                            byte[] prev = previous.get();
                            
                            if (!(prev != null && Arrays.equals(frame, prev))) {
                                client.writeToServerLog(Log.LEVEL_INFO, "Sending next frame");

                                net.packet.RemoteDesktopFrame packet = new net.packet.RemoteDesktopFrame();

                                packet.image = frame;

                                client.sendUDP(packet);
                            }
                            
                            previous.set(frame);
                        }

                        Thread.sleep(timeBetweenFrames);
                    }
                } catch (InterruptedException | IOException ex) {
                    client.writeToServerLog(Log.LEVEL_ERROR, "[RemoteDesktopManager] Failed to sleep in the thread", ex);
                }
            }
        });

        t.start();
    }

}
